/*
 * 컴파일을 위해 올려 놓은 소스 입니다.
 * 서버에 반영하지 마시고 다른국가에 적용할 경우 서버에 있는 class 를 카피해서 사용하십시오.
 * 
 */
/*
 * Created on 2004. 9. 24.
 *
 * To change the template for this generated file go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
package com.pushmsg.OmaOtaConf;

import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import com.sun.crypto.provider.SunJCE; 
//import cryptix.jce.provider.CryptixCrypto; 
/**
 * @author dgchun
 *
 * To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
public class OmaOtaWspHdr{
	
	/*
	 * The following is a hex-encoding of a CP WSP header without security (USERPIN, NETWPIN, etc):

		0x01 // TID (Transaction ID). S-Unit-Push.req::Push Id. See [WSP] Ch. 8.2.1
		0x06 // PDU Type = PUSH. See [WSP] Ch. 8.2.1 + App. A
		0x03 // HeadersLen. Length of rest of WSP header
		0x1F // ValueLengthQuote. This is necessary although it should not. See [WSP) Ch, 8.4.2.2
		0x01 // ValueLength = 1
		0xB6 // ContentType= S-Push.req::Push. This is 0x36 with "high-bit set", ie 0x36+0x80. See [ProvCont]

		final private byte pushid = 0x01;  //PUSH ID / Transaction ID
		final private byte pdutype = 0x06; //PDU type(push)	
		final private byte hdrlen = 0x06;  //Headerslength(content type + headers)
		final private byte lenquote = 0x1F; //Length-quote
		final private byte length = 0x00;		
		
		The next one is an example hex-encoding of a CP WSP header with USERPIN. Information about the generation of the MAC can be found HERE.
		
		0x01 // TID (Transaction ID). S-Unit-Push.req::Push Id. See [WSP] Ch. 8.2.1
		0x06 // PDU Type = PUSH. See [WSP] Ch. 8.2.1 + App. A
		0xNN // HeadersLen. Length of rest of WSP header. This is length of MAC + 7
		0x1F // ValueLengthQuote. Length > 30 and necessary to quote. See [WSP) Ch, 8.4.2.2
		0xYY // ValueLength = Length of MAC + 5
		0xB6 // ContentType= S-Push.req::Push. This is 0x36 with "high-bit set", ie 0x36+0x80. See [ProvCont]
		0x9181 // SEC = USERPIN
		0x92 // MAC Value ID
		nnnnn // MAC Value, MAC-length of bytes
		nnnnn // MAC Value, MAC-length of bytes
		nnnnn // MAC Value, MAC-length of bytes
		0x00 // End-of-MAC tag
		
		final private byte pushid = 0x01;  //PUSH ID / Transaction ID
		final private byte pdutype = 0x06; //PDU type(push)	
		final private byte hdrlen = 0x2F;  //Headerslength(content type + headers)
		final private byte lenquote = 0x1F; //Length-quote
		final private byte length = 0x2D;
		final private byte length = 0x00;		
	 */
	
	final private byte pushid = 0x01;  //PUSH ID / Transaction ID
	final private byte pdutype = 0x06; //PDU type(push)	
	final private byte hdrlen = 0x03;  //Headerslength(content type + headers)
	final private byte lenquote = 0x1F; //Length-quote
	final private byte length = 0x01;
	final private byte contenttype = (byte)0xB6; //apllication/vnd.wap.connectivity-wbxml
	
	//final private byte secParam =  (byte)0x91; //0x80 | 0x11(SEC)
	//private byte secVal = (byte)0x00; //user PIN 
	//final private byte macParam = (byte)0x92; //0x80 | 0x12(MAC)	
	private byte[] macVal = new byte[40];
	private byte[] data = null;
	String pin = null;
	String pinType = null;
	
	public OmaOtaWspHdr(){
//		data = new byte[49+1];
		data = new byte[6];
	}
	
	public void setPin(String pin){
		this.pin = pin;
	}
	
	/*
	public void setPinType(String type){
		
		this.pinType = type;
		if(pinType.equals("userpin"))
			secVal = (byte)0x81;
		else if(pinType.equals("netwpin"))
			secVal = (byte)0x80;
	}
	*/
	public void CalculateMac(byte[] buf){
		
		byte[] key = null;
		if(pinType.equals("userpin"))
			key = pin.getBytes();
		else if(pinType.equals("netwpin"))
			key = makeSemiOctet();
		//System.out.println(bytesToHex(key));
		Security.addProvider(new SunJCE());	
		
		//Provider[] prov = Security.getProviders();
		//for(int i=0; i<prov.length; i++)
		//	System.out.println(prov[i].getName());
		
		if (!"".equals(pinType) ){
			try{			
				SecretKey SHA1key = (SecretKey)new SecretKeySpec(key,"HmacSHA1"); //"HMAC-SHA-1");
				Mac hmac = Mac.getInstance("HmacSHA1"); // "HMAC-SHA-1");
				hmac.init(SHA1key);
				hmac.update(buf);
				byte[] cs = hmac.doFinal();
				String strCs = bytesToHex(cs);
				System.arraycopy(strCs.getBytes(), 0, macVal, 0, strCs.length());
				//System.out.println(bytesToHex(buf));
				//System.out.println(key);
//				System.out.println(strCs.length());
			}catch(Exception e){
				e.printStackTrace();
				System.out.println(e.getMessage());
			}
		}
	}
	
	private byte[] makeSemiOctet(){
		
		byte[] buf = new byte[8];		
		byte[] tmp = pin.getBytes();
//		System.out.println("LEN=" + tmp.length);
		int ndx = 0;
		
		buf[0] = (byte)((byte)(tmp[ndx] - 0x30)<<4);
		buf[0] |= (byte)0x09;
		
//		System.out.println("ndx= " + 0 + " value= " + buf[0]);
		int j;
		for(j=1; j<=7; j++)
		{
			buf[j] = (byte)((byte)(tmp[ndx+2] - 0x30)<<4);
			buf[j] |= (byte)(tmp[ndx+1] - 0x30);
						
			//System.out.println(ndx + " ndx= " + j + " value= " + buf[j]);
			
			ndx += 2;			
		}
		String strTmp = bytesToHex(buf);
//		System.out.println(bytesToHex(buf));
		return buf;
		//return strTmp.getBytes();
	}
	
	/*
	public void setSEC(byte val){
		secVal = val;
	}
	*/
	public int getLength(){
		return data.length;
	}
	
	public byte[] getData(){
		int ndx=0;
		
		data[ndx++] = pushid;
		data[ndx++] = pdutype;
		data[ndx++] = hdrlen;
		data[ndx++] = lenquote;
		data[ndx++] = length;
		data[ndx++] = contenttype;
//		data[ndx++] = secParam;
//		data[ndx++] = secVal;
//		data[ndx++] = macParam;
//		System.arraycopy(macVal, 0, data, ndx, macVal.length);
//		ndx += macVal.length;
//		data[ndx++] = 0x00;
		return data;
	}
	
	private String bytesToHex(byte[] data) {
		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < data.length; i++) {
			buf.append(byteToHex(data[i]).toUpperCase());
		}
		return (buf.toString());
	}
	
	private String byteToHex(byte data) {
		StringBuffer buf = new StringBuffer();
		buf.append(toHexChar((data >>> 4) & 0x0F));
		buf.append(toHexChar(data & 0x0F));
		return buf.toString();
	}

	private char toHexChar(int i) {
		if ((0 <= i) && (i <= 9)) {
			return (char) ('0' + i);
		}
		else {
			return (char) ('a' + (i - 10));
		}
	}
}
